开源与跨平台的 JavaScript 运行时环境

运行于单个进程中,无需为每个请求创建新的线程

异步I/O、非阻塞。执行 I/O 操作时(例如从网络读取、访问数据库或文件系统),Node.js 会在响应返回时恢复操作,而不是阻塞线程并浪费 CPU 循环等待。——> 高并发

# 什么是 Node.js

# 官方定义

  • Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
  • Node.js 使用了一个事件驱动非阻式I/O 的模型,使其轻量且高效。

# Node.js 中与 Chrome 中写 JS 有什么区别

  • Node.js 没有浏览器 API,即 document、window 等
  • 加入了许多 Node.js API
  • Chrome 中写 JS 控制浏览器,Node.js 中写 JS 控制整个计算机

# Node.js 好在哪

# 在处理高并发、I/O 密集场景性能优势明显

CPU 密集:压缩、解压、加密、解密、运算

I/O 密集:文件操作、网络操作、数据库读写

web 常见场景:

  • 静态资源读取
  • 数据库操作
  • 渲染页面

高并发应对之道:

  • 增加机器数
  • 增加每台机器的 CPU 数 —— 多核

Node.js 的单线程

  • 单线程只是针对主进程,操作系统底层的多线程调度来完成 I/O
  • 单线程并不是单进程

# Node.js 可以用来做什么

# 现阶段应用领域

  • web 服务中间层 - web server
  • 构建工作流 - 本地代码构建(属于cpu密集,从性能考虑并不适合node来做,但因为前端熟悉js)
  • 实用小工具开发 - 脚本工具、爬虫等
  • 客户端应用

# web 服务中间层

# 实例

腾讯视频

# 原因
  1. 搜索引擎优化 + 首屏加速 = 服务端渲染
  2. 服务端渲染 + 前后端同构 = Node.js

# 构建工作流

# 实例
  1. gulp
  2. webpack
# 原因
  1. 前端构建工具是为了构建前端代码 = 使用对象是前端开发
  2. 功能需要扩展、问题需要修复 = 前端开发看得懂、能解决 = Node.js

# 客户端应用

# 实例
  1. VS Code
  2. 游戏 - wayward
# 原因

​ 使用 Node.js 的客户端技术 Electron

# 安装(3m安装法)

# nvm( node 版本安装及管理工具 )

  1. 安装 nvm

    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.1/install.sh | bash

  2. 查看可安装node版本

    nvm ls-remote

  3. 安装node

    nvm install 14.15.1

    nvm install 8

  4. 查看本机已安装版本

    nvm ls

  5. 切换版本

    nvm use 14.15.1

  6. 指定默认版本

    切换到目标版本后 nvm alias default node

  7. 重新安装全局模块

    通过某个版本node自带的npm安装的全局模块,仅能在当前版本node环境使用,若要使node v14.15.1上安装的全局模块在其它node版本中共用,可执行

    nvm reinstall-packages 14.15.1

# npm( nodejs 包下载工具)

  1. 安装npm

    因为npm本身也是一个Node.js模块,所以可以通过 npm 来安装

    npm install -g npm@2.9

  2. 常用选项

    无选项 安装到 node_module ,但不保存到 package.json

    --global/-g 安装到全局,如果是命令行模块,会直接链接到环境变量里

    --save/-S 安装 node_module ,并保存在 package.json 里的 dependencies ,表示生产环境依赖的模块

    --save-dev/-D 安装 node_module ,并保存在 package.json 里的 devDependencies ,表示开发环境依赖的模块

# nrm( npm 镜像源切换)

  1. 安装

    npm install -g nrm 因为是命令行模块,所以需要全局安装

  2. 查看源

    nrm ls npm、cnpm、yarn、taobao等

  3. 测速

    nrm test

  4. 切换源

    nrm use cnpm

  5. 增加源

    为了保证开发效率,企业在内网部署一套私有 npm 源是非常有必要的。推荐使用 cnpm 部署私有源镜像服务器。

    nrm add 自定义指令名 企业镜像地址

# Node.js 基础

# 什么是技术预研

  • 分析要做的需求,找出技术难点
  • 针对每个技术难点进行攻克

# BFF 层

即 Backend For Frondend,就是前端和服务端之间的中间渲染层

  • 对用户侧提供 HTTP 服务
  • 使用后端 RPC(Romote Procedure Call远程过程调用) 服务

# 模块:CommonJS 规范

# 的问题
  • 脚本变多时,需要手动管理加载顺序
  • 不同脚本之间逻辑调用,需要通过全局变量的方式
  • 没有 html 安放 script 怎么办?例如 nodejs 中就没有 html
# CommonJS 模块规范
  • 每个文件是一个模块,有自己的作用域
  • 模块内部 module 变量代表模块本身
  • module.exports 属性代表模块对外接口

待整理:规范、exports与module.exports、webpack打包出来的文件

exports 是 module.exports 的快捷方式,common.js 中对外暴露的永远都是module.exports,而exports只是它的引用,所以不能直接给exports赋值,因为赋值会修改exports的指向,只能exports.xx = xx 这样挂载的方式使用。

# require特性
  • module 被加载时执行,加载后缓存
  • 循环加载时,只输出已执行的部分,还未执行的部分不会输出

# global

  • commonjs
  • buffer、process、console
  • timer
  • process.nextTick 放入当前事件队列的队尾,setImmediate 放入下一个队列的队首,setTimeout 介于两者之间

# path

  • __dirname、__filename 总是返回文件的绝对路径
  • process.cwd() 总是返回执行 node 命令所在的文件夹

# ./

  • 在 require 的参数中总是相对当前文件所在的文件夹
  • 在其它地方和 process.cwd() 一样,相对 node 启动文件夹

# Buffer

  • 用来处理二进制数据流
  • 实例类似整数数组,大小固定,默认16进制表示
  • 利用C++代码在V8堆外分配物理内存

# 内置模块

负责nodejs的应用层面到操作系统层面的通信,包括nodejs调用操作系统的能力或者说操作系统通知nodejs的能力。有了内置模块,nodejs就具有了强大的和操作系统交互的能力,从而可以做出服务端应用的能力。

TODO: 内置模块运行机制 极客时间《Node.js开发实战》12-Node.js内置模块

# 异步:非阻塞I/O

I/O 即 Input/Output,一个系统的输入和输出

阻塞 I/O 和非阻塞 I/O 的区别就在于系统接收输入再到输出期间,能不能接收其它输入

nodejs 线程通过事件循环调度其它 C++ 线程来异步处理任务,实现了整个 nodejs 的非阻塞 I/O。

# 异步:异步编程之 callback

回调函数规范:error-first callback,即第一个参数是error,后面的参数才是结果。

# 异步流程控制

常见恶心场景:

  1. 回调地狱;
  2. 并行执行

# 事件循环

代码模拟:

const eventloop = {
		queue: [],
		
		loop() {
				while (this.queue.length) {
						const callback = this.queue.shift()
						callback()
				}
				
				setTimeout(this.loop.bind(this), 50)
		},
		
		add(callback) {
				this.queue.push(callback)
		}
}

eventloop.loop()

setTimeout(() => {
		eventloop.add(() => {
				console.log(1)
		})
}, 500)

setTimeout(() => {
		eventloop.add(() => {
				console.log(2)
		})
}, 800)

# 异步:异步编程之Promise

当前的事件循环得不到的结果,但未来的事件循环会给到你结果。

执行 then 和 catch 会返回一个新的 Promise,该 Promise 最终状态根据 then 和 catch 的回调函数的执行结果决定:

  • 如果回调函数最终是 throw,该 Promise 是 rejected 状态
  • 如果回调函数最终是 return,该 Promise 是 resolved 状态
  • 如果回调函数最终 return 了一个 Promise,该 Promise 会和回调函数 return 的 Promise 状态保持一致

# 异步:异步编程之async/await

  • 本质是 Promise 的语法糖
  • 异步编程的终极解决方案 - 以同步的方式写异步
    • await 关键字可以“暂停” async function 后边代码的执行
    • await 关键字可以以同步的写法获取 Promise 的执行结果
    • try-catch 可以获取 await 所得到的错误 - 一个穿越 事件循环而存在的 functio n

# ES6+知识点

# 生成器 Generator

返回一个迭代器,每个迭代器都有 next 方法,用来获取每次迭代生成的对象

node 模块 co 就是利用了 generator

最后更新时间: 5/18/2021, 8:03:02 AM